/**
 * 
 */
package gameTests;

import static org.junit.Assert.*;
import game.TileMap;
import game.Unit;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

import org.junit.Test;

/**
 * @author Lucas 'Mezmor' Pfister
 *
 */
public class MapTest {

	/**
	 * Test simple 5x5 map containing no units and only plains.
	 */
	@Test
	public void testMap() {
		String name = "Test Map 1";
		Unit[][] units = new Unit[5][5];
		String[][] terrain = new String[5][5];
		
		for(int row = 0; row < units.length; row++){
			for(int col = 0; col < units[0].length; col++){
				terrain[row][col] = "100";
			}
		}
		
		TileMap testMap = new TileMap(name, units, terrain);
		TileMap deserializedTestMap = null;
		
		// Serialize it
		try {
			testMap.serialize();
		} catch (IOException i) {
			i.printStackTrace();
			fail();
		}
		
		// Deserialize it
		try {
			deserializedTestMap = new TileMap(name);
		} catch (ClassNotFoundException | IOException e) {
			e.printStackTrace();
			fail();
		}
		
		assertEquals(name, deserializedTestMap.getName());
		assertEquals(5, deserializedTestMap.getHeight());
		assertEquals(5, deserializedTestMap.getWidth());
		Unit[][] actualUnits = deserializedTestMap.getUnits();
		String[][] actualTerrain = deserializedTestMap.getTerrain();
		
		for(int row = 0; row < units.length; row++){
			for(int col = 0; col < units[0].length; col++){
				assertEquals(units[row][col], actualUnits[row][col]);
				assertEquals(terrain[row][col], actualTerrain[row][col]);
			}
		}
	}
	
	@Test
	public void testMultiTerrainMap(){
		String name = "Test Map 2";
		Unit[][] units = new Unit[5][5];
		String[][] terrain = new String[5][5];
		
		for(int row = 0; row < units.length; row++){
			for(int col = 0; col < units[0].length; col++){
				if(col % 2 == 0)
					terrain[row][col] = "000";
				else
					terrain[row][col] = "100";
			}
		}
		
		TileMap testMap = new TileMap(name, units, terrain);
		
		try {
			testMap.serialize();
		} catch (IOException e) {
			e.printStackTrace();
			fail();
		}
		
		TileMap deserializedTestMap = null;
		
		try {
			deserializedTestMap = new TileMap(name);
		} catch (ClassNotFoundException | IOException e) {
			e.printStackTrace();
			fail();
		}
		
		assertEquals(name, deserializedTestMap.getName());
		assertEquals(5, deserializedTestMap.getHeight());
		assertEquals(5, deserializedTestMap.getWidth());
		Unit[][] actualUnits = deserializedTestMap.getUnits();
		String[][] actualTerrain = deserializedTestMap.getTerrain();
		
		for(int row = 0; row < units.length; row++){
			for(int col = 0; col < units[0].length; col++){
				assertEquals(units[row][col], actualUnits[row][col]);
				assertEquals(terrain[row][col], actualTerrain[row][col]);
			}
		}
	}

	@Test
	public void test10x10Map(){
		String name = "Test Map 10x10";
		String[][] terrain = { 
				{"100", "100", "100", "100", "131", "100", "100", "100", "100", "100"}, 
				{"100", "100", "100", "100", "102", "100", "100", "100", "100", "100"},
				{"100", "000", "100", "100", "102", "100", "100", "100", "000", "100"},
				{"100", "000", "100", "100", "102", "100", "100", "100", "000", "100"},
				{"100", "000", "100", "100", "102", "100", "100", "100", "000", "100"},
				{"100", "012", "001", "001", "002", "001", "001", "001", "032", "100"},
				{"100", "100", "100", "100", "102", "100", "100", "100", "100", "100"},
				{"100", "100", "100", "100", "102", "100", "100", "100", "100", "100"},
				{"100", "100", "100", "100", "102", "100", "100", "100", "100", "100"},
				{"100", "100", "100", "100", "112", "100", "100", "100", "100", "100"}
		};
		
		Unit[][] units = new Unit[10][10];
		
		TileMap testMap = new TileMap(name, units, terrain);

		try {
			testMap.serialize();
		} catch (IOException e) {
			e.printStackTrace();
			fail();
		}

		TileMap deserializedTestMap = null;

		try {
			deserializedTestMap = new TileMap(name);
		} catch (ClassNotFoundException | IOException e) {
			e.printStackTrace();
			fail();
		}

		assertEquals(name, deserializedTestMap.getName());
		assertEquals(10, deserializedTestMap.getHeight());
		assertEquals(10, deserializedTestMap.getWidth());
		Unit[][] actualUnits = deserializedTestMap.getUnits();
		String[][] actualTerrain = deserializedTestMap.getTerrain();

		for (int row = 0; row < units.length; row++) {
			for (int col = 0; col < units[0].length; col++) {
				assertEquals(units[row][col], actualUnits[row][col]);
				assertEquals(terrain[row][col], actualTerrain[row][col]);
			}
		}
	}
	
	@Test
	public void test20x20Map(){
		String name = "Test Map 21x21";
		Unit[][] units = new Unit[21][21];
		String[][] terrain = {
				{"100", "100", "100", "100", "100", "401", "311", "311", "311", "311", "311", "311", "311", "311", "311", "311", "311", "311", "311", "311", "311"},
				{"100", "100", "100", "100", "100", "401", "311", "311", "311", "311", "412", "311", "311", "311", "311", "311", "311", "311", "311", "311", "311"},
				{"100", "100", "100", "100", "100", "002", "002", "002", "002", "002", "100", "401", "311", "311", "311", "311", "311", "311", "311", "311", "311"},
				{"100", "100", "100", "100", "100", "401", "311", "311", "311", "311", "022", "311", "311", "311", "311", "311", "311", "311", "311", "311", "311"},
				{"100", "100", "100", "100", "100", "401", "311", "311", "311", "311", "022", "311", "311", "311", "311", "311", "311", "311", "311", "311", "311"},
				{"410", "410", "022", "410", "410", "311", "311", "311", "311", "311", "022", "311", "311", "311", "311", "311", "311", "311", "311", "311", "311"},
				{"311", "311", "022", "311", "311", "311", "311", "311", "412", "412", "022", "412", "412", "311", "311", "311", "311", "311", "311", "311", "311"},
				{"311", "311", "022", "311", "311", "311", "311", "421", "100", "100", "100", "100", "100", "401", "311", "311", "311", "311", "311", "311", "311"},
				{"311", "311", "022", "311", "311", "311", "311", "421", "100", "100", "100", "100", "100", "401", "311", "311", "311", "311", "311", "311", "311"},
				{"311", "311", "022", "311", "311", "311", "311", "421", "100", "100", "100", "100", "100", "401", "311", "311", "311", "311", "412", "311", "311"},
				{"311", "421", "100", "002", "002", "002", "002", "002", "100", "100", "100", "100", "100", "002", "002", "002", "002", "002", "100", "401", "311"},
				{"311", "311", "410", "311", "311", "311", "311", "421", "100", "100", "100", "100", "100", "401", "311", "311", "311", "311", "022", "311", "311"},
				{"311", "311", "311", "311", "311", "311", "311", "421", "100", "100", "100", "100", "100", "401", "311", "311", "311", "311", "022", "311", "311"},
				{"311", "311", "311", "311", "311", "311", "311", "421", "100", "100", "100", "100", "100", "401", "311", "311", "311", "311", "022", "311", "311"},
				{"311", "311", "311", "311", "311", "311", "311", "311", "410", "410", "022", "410", "410", "311", "311", "311", "311", "311", "022", "311", "311"},
				{"311", "311", "311", "311", "311", "311", "311", "311", "311", "311", "022", "311", "311", "311", "311", "311", "412", "412", "022", "412", "412"},
				{"311", "311", "311", "311", "311", "311", "311", "311", "311", "311", "022", "311", "311", "311", "311", "421", "100", "100", "100", "100", "100"},
				{"311", "311", "311", "311", "311", "311", "311", "311", "311", "311", "022", "311", "311", "311", "311", "421", "100", "100", "100", "100", "100"},
				{"311", "311", "311", "311", "311", "311", "311", "311", "311", "421", "100", "002", "002", "002", "002", "002", "100", "100", "100", "100", "100"},
				{"311", "311", "311", "311", "311", "311", "311", "311", "311", "311", "410", "311", "311", "311", "311", "421", "100", "100", "100", "100", "100"},
				{"311", "311", "311", "311", "311", "311", "311", "311", "311", "311", "311", "311", "311", "311", "311", "421", "100", "100", "100", "100", "100"}
		};
		
		TileMap testMap = new TileMap(name, units, terrain);
		try {
			testMap.serialize();
		} catch (IOException e1) {
			e1.printStackTrace();
		}
		
		TileMap deserializedTestMap = null;
		try {
			deserializedTestMap = new TileMap(name);
		} catch (ClassNotFoundException | IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		assertEquals(name, deserializedTestMap.getName());
		assertEquals(21, deserializedTestMap.getHeight());
		assertEquals(21, deserializedTestMap.getWidth());
		Unit[][] actualUnits = deserializedTestMap.getUnits();
		String[][] actualTerrain = deserializedTestMap.getTerrain();

		for (int row = 0; row < units.length; row++) {
			for (int col = 0; col < units[0].length; col++) {
				assertEquals(units[row][col], actualUnits[row][col]);
				assertEquals(terrain[row][col], actualTerrain[row][col]);
			}
		}
	}
	
	@Test
	public void testBadRows(){
		String name = "Failed Map";
		Unit[][] units = new Unit[3][5];
		String[][] terrain = new String[5][5];
		
		try{
			TileMap tileMap = new TileMap(name, units, terrain);
			fail();
		} catch(IllegalArgumentException e){
		}
	}
	
	@Test
	public void testBadCols(){
		String name = "Failed Map";
		Unit[][] units = new Unit[5][3];
		String[][] terrain = new String[5][5];
		
		try{
			TileMap tileMap = new TileMap(name, units, terrain);
			fail();
		} catch(IllegalArgumentException e){
		}
	}
	
	@Test
	public void testBadDimensions(){
		String name = "Failed Map";
		Unit[][] units = new Unit[3][4];
		String[][] terrain = new String[5][5];
		
		try{
			TileMap tileMap = new TileMap(name, units, terrain);
			fail();
		} catch(IllegalArgumentException e){
		}
	}
	
	/**
	 * Test method for {@link game.MapLoader#getUnits()}.
	 */
	@Test
	public void testGetUnits() {
		fail("Not yet implemented");
	}

	/**
	 * Test method for {@link game.MapLoader#getMap()}.
	 */
	@Test
	public void testGetMap() {
		fail("Not yet implemented");
	}

}
